"""
WebSocket权限控制和数据过滤
============================

实现细粒度的权限控制：
1. 用户权限验证
2. 数据访问控制
3. 速率限制
4. 订阅权限管理
"""

import logging
from typing import Dict, List, Set, Optional, Any
from datetime import datetime, timedelta
from dataclasses import dataclass, field
from enum import Enum

logger = logging.getLogger(__name__)


class PermissionLevel(Enum):
    """权限级别"""
    GUEST = "guest"          # 访客：只读基础数据
    BASIC = "basic"          # 基础：实时行情
    PREMIUM = "premium"      # 高级：深度行情 + 历史数据
    PROFESSIONAL = "professional"  # 专业：全量数据 + API
    ADMIN = "admin"          # 管理员：所有权限


class DataCategory(Enum):
    """数据类别"""
    REALTIME_QUOTE = "realtime_quote"      # 实时行情
    HISTORICAL_DATA = "historical_data"    # 历史数据
    DEPTH_DATA = "depth_data"              # 深度行情
    INDEX_DATA = "index_data"              # 指数数据
    FUNDAMENTAL = "fundamental"            # 基本面数据
    TECHNICAL = "technical"                # 技术指标


@dataclass
class UserPermission:
    """用户权限"""
    user_id: str
    level: PermissionLevel
    allowed_categories: Set[DataCategory] = field(default_factory=set)
    allowed_symbols: Optional[Set[str]] = None  # None表示全部允许
    max_subscriptions: int = 10
    rate_limit_per_minute: int = 60
    expires_at: Optional[datetime] = None
    
    def can_access_category(self, category: DataCategory) -> bool:
        """检查是否可以访问数据类别"""
        return category in self.allowed_categories
    
    def can_access_symbol(self, symbol: str) -> bool:
        """检查是否可以访问特定股票"""
        if self.allowed_symbols is None:
            return True
        return symbol in self.allowed_symbols
    
    def is_expired(self) -> bool:
        """检查权限是否过期"""
        if self.expires_at is None:
            return False
        return datetime.now() > self.expires_at
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "user_id": self.user_id,
            "level": self.level.value,
            "allowed_categories": [cat.value for cat in self.allowed_categories],
            "allowed_symbols": list(self.allowed_symbols) if self.allowed_symbols else None,
            "max_subscriptions": self.max_subscriptions,
            "rate_limit_per_minute": self.rate_limit_per_minute,
            "expires_at": self.expires_at.isoformat() if self.expires_at else None
        }


class PermissionManager:
    """
    权限管理器
    
    功能：
    - 用户权限验证
    - 数据访问控制
    - 订阅限制
    - 速率限制
    """
    
    def __init__(self):
        """初始化权限管理器"""
        # 用户权限缓存
        self.user_permissions: Dict[str, UserPermission] = {}
        
        # 默认权限配置
        self.default_permissions = self._init_default_permissions()
        
        logger.info("PermissionManager initialized")
    
    def _init_default_permissions(self) -> Dict[PermissionLevel, UserPermission]:
        """初始化默认权限配置"""
        return {
            PermissionLevel.GUEST: UserPermission(
                user_id="",
                level=PermissionLevel.GUEST,
                allowed_categories={DataCategory.REALTIME_QUOTE, DataCategory.INDEX_DATA},
                max_subscriptions=3,
                rate_limit_per_minute=30
            ),
            PermissionLevel.BASIC: UserPermission(
                user_id="",
                level=PermissionLevel.BASIC,
                allowed_categories={
                    DataCategory.REALTIME_QUOTE,
                    DataCategory.INDEX_DATA,
                    DataCategory.HISTORICAL_DATA
                },
                max_subscriptions=10,
                rate_limit_per_minute=60
            ),
            PermissionLevel.PREMIUM: UserPermission(
                user_id="",
                level=PermissionLevel.PREMIUM,
                allowed_categories={
                    DataCategory.REALTIME_QUOTE,
                    DataCategory.INDEX_DATA,
                    DataCategory.HISTORICAL_DATA,
                    DataCategory.DEPTH_DATA,
                    DataCategory.TECHNICAL
                },
                max_subscriptions=50,
                rate_limit_per_minute=300
            ),
            PermissionLevel.PROFESSIONAL: UserPermission(
                user_id="",
                level=PermissionLevel.PROFESSIONAL,
                allowed_categories=set(DataCategory),  # 全部类别
                max_subscriptions=200,
                rate_limit_per_minute=1000
            ),
            PermissionLevel.ADMIN: UserPermission(
                user_id="",
                level=PermissionLevel.ADMIN,
                allowed_categories=set(DataCategory),
                max_subscriptions=1000,
                rate_limit_per_minute=10000
            )
        }
    
    def get_user_permission(self, user_id: str) -> UserPermission:
        """
        获取用户权限
        
        Args:
            user_id: 用户ID
        
        Returns:
            用户权限
        """
        # 从缓存获取
        if user_id in self.user_permissions:
            permission = self.user_permissions[user_id]
            
            # 检查是否过期
            if not permission.is_expired():
                return permission
            else:
                del self.user_permissions[user_id]
        
        # 从数据库加载（这里简化为返回默认权限）
        # TODO: 实际应该从数据库查询用户权限
        return self._load_user_permission_from_db(user_id)
    
    def _load_user_permission_from_db(self, user_id: str) -> UserPermission:
        """
        从数据库加载用户权限
        
        Args:
            user_id: 用户ID
        
        Returns:
            用户权限
        """
        # TODO: 实际实现应该查询数据库
        # 这里简化为返回基础权限
        default = self.default_permissions[PermissionLevel.BASIC]
        permission = UserPermission(
            user_id=user_id,
            level=default.level,
            allowed_categories=default.allowed_categories.copy(),
            max_subscriptions=default.max_subscriptions,
            rate_limit_per_minute=default.rate_limit_per_minute
        )
        
        # 缓存权限
        self.user_permissions[user_id] = permission
        
        return permission
    
    def check_access(
        self,
        user_id: str,
        category: DataCategory,
        symbol: Optional[str] = None
    ) -> bool:
        """
        检查用户是否有访问权限
        
        Args:
            user_id: 用户ID
            category: 数据类别
            symbol: 股票代码（可选）
        
        Returns:
            是否有权限
        """
        permission = self.get_user_permission(user_id)
        
        # 检查类别权限
        if not permission.can_access_category(category):
            logger.warning(f"User {user_id} denied access to category {category.value}")
            return False
        
        # 检查股票权限
        if symbol and not permission.can_access_symbol(symbol):
            logger.warning(f"User {user_id} denied access to symbol {symbol}")
            return False
        
        return True
    
    def check_subscription_limit(
        self,
        user_id: str,
        current_subscriptions: int
    ) -> bool:
        """
        检查订阅数限制
        
        Args:
            user_id: 用户ID
            current_subscriptions: 当前订阅数
        
        Returns:
            是否在限制内
        """
        permission = self.get_user_permission(user_id)
        return current_subscriptions < permission.max_subscriptions
    
    def get_rate_limit(self, user_id: str) -> int:
        """
        获取用户速率限制
        
        Args:
            user_id: 用户ID
        
        Returns:
            每分钟请求限制
        """
        permission = self.get_user_permission(user_id)
        return permission.rate_limit_per_minute
    
    def update_user_permission(self, permission: UserPermission):
        """更新用户权限"""
        self.user_permissions[permission.user_id] = permission
        logger.info(f"Updated permission for user {permission.user_id}")
    
    def revoke_user_permission(self, user_id: str):
        """撤销用户权限"""
        if user_id in self.user_permissions:
            del self.user_permissions[user_id]
            logger.info(f"Revoked permission for user {user_id}")


class DataFilter:
    """
    数据过滤器
    
    根据用户权限过滤数据
    """
    
    def __init__(self, permission_manager: PermissionManager):
        """
        初始化数据过滤器
        
        Args:
            permission_manager: 权限管理器
        """
        self.permission_manager = permission_manager
        
        logger.info("DataFilter initialized")
    
    def filter_market_data(
        self,
        user_id: str,
        data: Dict[str, Any],
        category: DataCategory
    ) -> Optional[Dict[str, Any]]:
        """
        过滤市场数据
        
        Args:
            user_id: 用户ID
            data: 原始数据
            category: 数据类别
        
        Returns:
            过滤后的数据，如果无权限返回None
        """
        # 检查权限
        symbol = data.get('symbol')
        if not self.permission_manager.check_access(user_id, category, symbol):
            return None
        
        # 根据权限级别过滤字段
        permission = self.permission_manager.get_user_permission(user_id)
        
        if permission.level == PermissionLevel.GUEST:
            # 访客只能看基础字段
            return self._filter_basic_fields(data)
        elif permission.level == PermissionLevel.BASIC:
            # 基础用户可以看常规字段
            return self._filter_standard_fields(data)
        else:
            # 高级用户可以看全部字段
            return data
    
    def _filter_basic_fields(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """过滤基础字段（访客）"""
        basic_fields = {
            'symbol', 'name', 'price', 'change', 'change_percent',
            'volume', 'timestamp'
        }
        return {k: v for k, v in data.items() if k in basic_fields}
    
    def _filter_standard_fields(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """过滤标准字段（基础用户）"""
        excluded_fields = {
            'order_book', 'level2_data', 'internal_metadata'
        }
        return {k: v for k, v in data.items() if k not in excluded_fields}
    
    def filter_batch_data(
        self,
        user_id: str,
        data_list: List[Dict[str, Any]],
        category: DataCategory
    ) -> List[Dict[str, Any]]:
        """
        批量过滤数据
        
        Args:
            user_id: 用户ID
            data_list: 数据列表
            category: 数据类别
        
        Returns:
            过滤后的数据列表
        """
        filtered_list = []
        
        for data in data_list:
            filtered = self.filter_market_data(user_id, data, category)
            if filtered is not None:
                filtered_list.append(filtered)
        
        return filtered_list


class SubscriptionValidator:
    """
    订阅验证器
    
    验证用户的订阅请求
    """
    
    def __init__(self, permission_manager: PermissionManager):
        """
        初始化订阅验证器
        
        Args:
            permission_manager: 权限管理器
        """
        self.permission_manager = permission_manager
        
        # 用户当前订阅计数
        self.user_subscriptions: Dict[str, Set[str]] = {}
        
        logger.info("SubscriptionValidator initialized")
    
    def validate_subscription(
        self,
        user_id: str,
        symbols: List[str],
        category: DataCategory
    ) -> tuple[bool, Optional[str]]:
        """
        验证订阅请求
        
        Args:
            user_id: 用户ID
            symbols: 要订阅的股票代码列表
            category: 数据类别
        
        Returns:
            (是否有效, 错误信息)
        """
        # 1. 检查数据类别权限
        if not self.permission_manager.check_access(user_id, category):
            return False, f"No permission to access {category.value}"
        
        # 2. 检查订阅数限制
        current_subs = self.user_subscriptions.get(user_id, set())
        new_total = len(current_subs) + len(symbols)
        
        if not self.permission_manager.check_subscription_limit(user_id, new_total):
            permission = self.permission_manager.get_user_permission(user_id)
            return False, f"Subscription limit exceeded (max: {permission.max_subscriptions})"
        
        # 3. 检查每个股票的权限
        for symbol in symbols:
            if not self.permission_manager.check_access(user_id, category, symbol):
                return False, f"No permission to access symbol {symbol}"
        
        return True, None
    
    def add_subscriptions(self, user_id: str, symbols: List[str]):
        """添加订阅"""
        if user_id not in self.user_subscriptions:
            self.user_subscriptions[user_id] = set()
        
        self.user_subscriptions[user_id].update(symbols)
        
        logger.info(
            f"User {user_id} subscriptions updated: "
            f"{len(self.user_subscriptions[user_id])} symbols"
        )
    
    def remove_subscriptions(self, user_id: str, symbols: List[str]):
        """移除订阅"""
        if user_id in self.user_subscriptions:
            self.user_subscriptions[user_id].difference_update(symbols)
    
    def get_user_subscriptions(self, user_id: str) -> Set[str]:
        """获取用户订阅"""
        return self.user_subscriptions.get(user_id, set())
    
    def clear_user_subscriptions(self, user_id: str):
        """清空用户订阅"""
        if user_id in self.user_subscriptions:
            del self.user_subscriptions[user_id]


# 全局实例
_permission_manager: Optional[PermissionManager] = None
_data_filter: Optional[DataFilter] = None
_subscription_validator: Optional[SubscriptionValidator] = None


def get_permission_manager() -> PermissionManager:
    """获取权限管理器"""
    global _permission_manager
    if _permission_manager is None:
        _permission_manager = PermissionManager()
    return _permission_manager


def get_data_filter() -> DataFilter:
    """获取数据过滤器"""
    global _data_filter
    if _data_filter is None:
        _data_filter = DataFilter(get_permission_manager())
    return _data_filter


def get_subscription_validator() -> SubscriptionValidator:
    """获取订阅验证器"""
    global _subscription_validator
    if _subscription_validator is None:
        _subscription_validator = SubscriptionValidator(get_permission_manager())
    return _subscription_validator

